package pwd.allen.tuomin;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.text.csv.CsvReader;
import cn.hutool.core.text.csv.CsvUtil;
import cn.hutool.core.text.csv.CsvWriter;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Db;
import cn.hutool.json.JSONUtil;
import org.yaml.snakeyaml.Yaml;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import java.sql.SQLException;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 * @author 门那粒沙
 * @create 2022-04-03 15:49
 **/
public class TuominUtil {

    public Db db = Db.use();

    public TuominConfig config;

    public TuominUtil() {
        db = Db.use();
        Yaml yaml = new Yaml();
        config = yaml.loadAs(IoUtil.getReader(this.getClass().getResourceAsStream("/config/tuomin.yml"), CharsetUtil.CHARSET_UTF_8), TuominConfig.class);
    }

    public void outputData() throws SQLException {
        List<String> sql_tableNames = db.query(config.getSqlTableNames(), String.class);
        if (CollUtil.isEmpty(sql_tableNames)) {
            System.out.println("表名为空！");
            return;
        }

        CsvWriter writer = CsvUtil.getWriter(String.format("%s\\Desktop\\dbData%s.csv", System.getProperty("user.home"), System.currentTimeMillis()), CharsetUtil.CHARSET_GBK);
        for (String tableName : sql_tableNames) {
            List<Map> list_data = null;
            try {
                list_data = db.query(config.getSqlList().replaceAll("\\$\\{table\\}", tableName), Map.class);
                if (CollUtil.isNotEmpty(list_data)) {
                    ArrayList<Object> list = new ArrayList<>();
                    list.add(Collections.singletonList(tableName));
                    list.add(list_data.get(0).keySet());
                    for (Map map_data : list_data) {
                        list.add(map_data.values().stream().map(
                                s -> s == null ? null : s.toString()
                                        .replaceAll(",", "，")
                                        .replaceAll("(\n|\r)", "")
                        ).collect(Collectors.toList()));
                    }
                    writer.write(list);
                    writer.writeLine();
                    writer.writeLine();
                }
            } catch (Exception e) {
                System.out.println(String.format("tableName查询失败：%s", e.toString()));
            }
        }
        writer.close();
    }


    public void matchRegex() throws IOException {
        final Map<String, Map<String, Map<String, Integer>>> map_tableName = new HashMap<>();

        Consumer<List<String[]>> consumer = lists -> {
            String tableName = lists.get(0)[0];
            String[] header = lists.get(1);
            Map<String, Integer> map_num = new HashMap<>();
            Map<String, Map<String, Integer>> map_field = new HashMap<>();
            for (int i = 2; i < lists.size(); i++) {
                String[] strings = lists.get(i);
                for (int j = 0; j < strings.length; j++) {
                    String data = strings[j];
                    if (j >= header.length) {
                        System.out.println(String.format("%s[%s][%s]下标越界！", tableName, i, j));
                        break;
                    }
                    if (StrUtil.isEmpty(data)) {
                        continue;
                    }
                    Integer num = map_num.get(header[j]);
                    if (num == null) {
                        map_num.put(header[j], 0);
                    }
                    map_num.put(header[j], map_num.get(header[j]) + 1);
                    for (Map.Entry<String, String> entry : config.getRules().entrySet()) {
                        if (data.matches(entry.getValue())) {
                            Map<String, Integer> map_rule = map_field.get(header[j]);
                            if (map_rule == null) {
                                map_rule = new HashMap<>();
                                map_field.put(header[j], map_rule);
                            }
                            if (!map_rule.containsKey(entry.getKey())) {
                                map_rule.put(entry.getKey(), 0);
                            }
                            map_rule.put(entry.getKey(), map_rule.get(entry.getKey()) + 1);
                        }
                    }
                }
            }

            if (CollUtil.isNotEmpty(map_field)) {
                for (String field : new HashSet<>(map_field.keySet())) {
                    Map<String, Integer> map_rule = map_field.get(field);
                    for (String rule : new HashSet<>(map_rule.keySet())) {
                        if (map_rule.get(rule) * 100 / map_num.get(field) < config.getPercent()) {
                            map_rule.remove(rule);
                        }
                    }
                    if (map_rule.size() == 0) {
                        map_field.remove(field);
                    }
                }
                if (map_field.size() == 0) {
                    map_tableName.remove(tableName);
                }
                if (CollUtil.isNotEmpty(map_field)) {
                    map_tableName.put(tableName, map_field);
                }
            }

        };

        CsvReader reader = CsvUtil.getReader();
        reader.read(new File(String.format("%s\\Desktop\\dbData.csv", System.getProperty("user.home"))), CharsetUtil.CHARSET_GBK);
        BufferedReader bReader = null;
        try {
            bReader = FileUtil.getReader(String.format("%s\\Desktop\\dbData.csv", System.getProperty("user.home")), CharsetUtil.CHARSET_GBK);
            String line = null;
            ArrayList<String[]> lists = new ArrayList<>();
            while ((line = bReader.readLine()) != null) {
                if (StrUtil.isNotEmpty(line)) {
                    lists.add(line.split(","));
                } else if (CollUtil.isNotEmpty(lists)) {
                    consumer.accept(lists);
                    lists = new ArrayList<>();
                }
            }
        } finally {
            if (bReader != null) {
                bReader.close();
            }
        }

        FileUtil.writeString(JSONUtil.toJsonPrettyStr(map_tableName)
                , String.format("%s\\Desktop\\result%s.json", System.getProperty("user.home"), System.currentTimeMillis())
                , CharsetUtil.defaultCharset());

        PrintWriter printWriter = FileUtil.getPrintWriter(
                String.format("%s\\Desktop\\result%s.sql", System.getProperty("user.home"), System.currentTimeMillis())
                , Charset.defaultCharset()
                , true);

        if (CollectionUtil.isNotEmpty(map_tableName)) {
            for (Map.Entry<String, Map<String, Map<String, Integer>>> entry_table : map_tableName.entrySet()) {
                String tableName = entry_table.getKey();
                printWriter.println("-- " + tableName);
                Map<String, Map<String, Integer>> map_field = entry_table.getValue();
                for (Map.Entry<String, Map<String, Integer>> entry_field : map_field.entrySet()) {
                    String field = entry_field.getKey();
                    for (String rule : entry_field.getValue().keySet()) {
                        String updateSql = config.getUpdateSqls().containsKey(rule) ? config.getUpdateSqls().get(rule) : config.getUpdateSqls().get("default");
                        if (StrUtil.isNotBlank(updateSql)) {
                            updateSql = updateSql.replaceAll("\\$\\{table\\}", tableName).replaceAll("\\$\\{field\\}", field);
                            printWriter.println(updateSql);
                        }
                    }
                }
                printWriter.println();
            }
        }
        printWriter.close();
    }

}
